/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package ua.yandex.collections;

/**
 *
 * @author Neophron
 */
public class MyArrayList implements MyList {

    public static final int STANDARTINITCAPACITY = 10;
    private Object[] array;
    private int size;
    private int capacity;

    public MyArrayList() {
        this(STANDARTINITCAPACITY);
    }

    public MyArrayList(int initialCapacity) {
        array = new Object[initialCapacity];
        size = 0;
        capacity = initialCapacity;
    }

    public void ensureCapacity(int minCapacity) {
        if (capacity < minCapacity) {
            Object[] newArray = new Object[minCapacity];
            System.arraycopy(array, 0, newArray, 0, size);
            array = newArray;
            capacity = minCapacity;
        }
    }

    @Override
    public Object[] toArray() {
        Object[] res = new Object[size];
        System.arraycopy(array, 0, res, 0, size);
        return res;
    }

    @Override
    public void add(Object e) {
        add(size, e);
    }

    @Override
    public void add(int index, Object e) {
        if (e == null) {
            return;
        }
        addAll(index, new Object[]{e});
    }

    @Override
    public void addAll(Object[] c) {
        addAll(size, c);
    }

    private void checkIndex(int index) {
        if (index > size) {
            throw new IllegalArgumentException();
        }
    }

    private void checkIndexForGet(int index) {
        if (index >= size) {
            throw new IllegalArgumentException();
        }
    }

    @Override
    public void addAll(int index, Object[] c) {
        if (c == null) {
            return;
        }
        checkIndex(index);
        if (capacity >= size + c.length) {
            Object[] newArray = new Object[capacity];
            System.arraycopy(array, 0, newArray, 0, index);
            System.arraycopy(c, 0, newArray, index, c.length);
            System.arraycopy(array, index, newArray,
                    index + c.length, size - index);
            array = newArray;
            size += c.length;
        } else {
            ensureCapacity(capacity * 2);
            addAll(index, c);
        }
    }

    @Override
    public Object get(int index) {
        checkIndexForGet(index);
        return array[index];
    }

    @Override
    public Object remove(int index) {
        checkIndexForGet(index);
        Object res = array[index];
        Object[] newArray = new Object[capacity - 1];
        System.arraycopy(array, 0, newArray, 0, index);
        System.arraycopy(array, index + 1, newArray, index, size - index - 1);
        array = newArray;
        size--;
        return res;
    }

    @Override
    public void set(int index, Object e) {
        checkIndexForGet(index);
        array[index] = e;
    }

    @Override
    public int indexOf(Object o) {
        for (int i = 0; i < size; i++) {
            if (array[i].equals(o)) {
                return i;
            }
        }
        return -1;
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public void clear() {
        size = 0;
        array = new Object[STANDARTINITCAPACITY];
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public String toString() {
        StringBuilder str = new StringBuilder();
        if (!isEmpty()) {
            str.append(array[0].toString());
        }
        for (int i = 1; i < size; i++) {
            str.append(", " + array[i].toString());
        }
        return str.toString();
    }
}
